
package machinelearning;

import java.util.Random;
import java.util.Vector;

/**
 * Utilities for Vectors of Doubles
 * @author  Anat Nesichi & Moshe Goren
 */
public class DoubleVectorUtils
{   

    static Vector<Double> resVect; 
    
    // The random seed should be done once per run (not each function call):
    static Random rand = new Random(System.currentTimeMillis());

    /**
     * Multiplies two vectors of Doubles
     * @param a
     * @param b
     * @return The result of the multiplication
     */
    static public Double MultiplyVectors(Vector<Double> a, Vector<Double> b)
    {
        double res = 0;

        if (a.size() == b.size())
        {
            for (int i = 0; i < a.size(); i++)
            {                
                res += a.get(i) * b.get(i);
            }
        }

        return new Double(res);
    }   

    /**
     * Adds two vectors together
     * @param a
     * @param b
     * @return The resulting vector
     */
    static synchronized public Vector<Double> AddVectors(Vector<Double> a, Vector<Double> b)
    {
        if (a.size() == b.size())
        {
            resVect = new Vector<Double>();
            for (int i = 0; i < a.size(); i++)
            {
                resVect.add(a.get(i) + b.get(i));
            }
        }

        return resVect;
    }

    /**
     * Multiplies a vector by a number
     * @param a 
     * @param num
     * @return The resulting vector
     */
    static synchronized public Vector<Double> MultiplyVector(Vector<Double> a, double num)
    {
        resVect = null;

        resVect = new Vector<Double>();
        for (Double currVal : a)
        {
            resVect.add(currVal.doubleValue() * num);
        }

        return resVect;
    }

    /**
     * Normalizes a vector
     * @param a The vector to be normalized
     * @return The normalized vector
     */
    static synchronized public Vector<Double> NormalizeVector(Vector<Double> a)
    {
        double norm = 0.0;
        resVect = new Vector<Double>();

        for (Double currVal : a)
        {
            norm += currVal.doubleValue() * currVal.doubleValue();
        }

        norm = Math.sqrt(norm);

        for (Double currVal : a)
        {
            resVect.add(currVal.doubleValue() / norm);
        }

        return resVect;
    }

    static synchronized public Vector<Double> RandomVector(int size)
    {
        resVect = new Vector<Double>();       

        for (int i = 0; i < size; i++)
        {
            double sign = 1.0;

            if (rand.nextBoolean())
            {
                sign = -1.0;
            }

            resVect.add(sign * rand.nextDouble());
        }

        return resVect;
    }

    static synchronized public Vector<Double> ConvertFromDoubleArray(double[] array, int length)
    {
        resVect = new Vector<Double>();
        resVect.ensureCapacity(length);

        for (int i = 0; i < length; i++)
        {
            resVect.add(array[i]);
        }

        return resVect;
    }
}
